package org.dallasrowing.logbook.report;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.sql.Connection;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRGraphics2DExporter;
import net.sf.jasperreports.engine.export.JRGraphics2DExporterParameter;

import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;

public class GenerateJasperReport {

    private static final PaletteData PALETTE = new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF);

	private Connection connection;
	private String report;
	private String compiledSource;
	private JasperPrint reportPrint;

	public GenerateJasperReport(Connection con, String report) throws ReportException
	{
		this.connection = con;
		this.report = report;
		this.compiledSource = report.replace(".jrxml", ".jasper");
		if (!isReportCached())
		{
			compileReport();
		}
    }
	
	private boolean isReportCached() {
		File cachedFile = new File(compiledSource);
		File reportFile = new File(report);
		
		if (!cachedFile.exists() || !cachedFile.canRead())
			return false;
		
		if (cachedFile.lastModified() < reportFile.lastModified())
			return false;
		
		return true;
	}

	private void compileReport() throws ReportException {
		try {
			JasperCompileManager.compileReportToFile(report, compiledSource);
		} catch (JRException e) {
			throw new ReportException("Could not initialize report", e);
		}
	}

	public JasperPrint generate(Map<String, ?> params) throws ReportException
	{
		try {
			reportPrint = JasperFillManager.fillReport(compiledSource, params, connection);
		} catch (JRException e) {
			throw new ReportException("could not generate report",e);
		}
			
		return reportPrint;
		
	}
	
	public void exportPDF(String fileName) throws ReportException
	{
		try {
			JasperExportManager.exportReportToPdfFile(reportPrint, fileName);
		} catch (JRException e) {
			throw new ReportException("could not export to PDF", e);
		}
	}

	public Image exportAsImage(Device parent) throws ReportException {
		
		try {
			BufferedImage awtImage = new BufferedImage(400,400, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = (Graphics2D) awtImage.getGraphics();
			try {
				JRGraphics2DExporter exporter = new JRGraphics2DExporter();
				exporter.setParameter(JRExporterParameter.JASPER_PRINT, reportPrint);
				exporter.setParameter(JRGraphics2DExporterParameter.GRAPHICS_2D, g2d);
				exporter.setParameter(JRGraphics2DExporterParameter.IGNORE_PAGE_MARGINS, true);
				exporter.exportReport();
				
				g2d.setColor(Color.BLACK);
				g2d.setStroke(new BasicStroke(1));
				g2d.drawRect(0, 0, 399, 399);
			} finally {
				g2d.dispose();
			}
			
			int[] imgData = ((DataBufferInt)awtImage.getData().getDataBuffer()).getData();
			ImageData imageData = new ImageData(awtImage.getWidth(), awtImage.getHeight(), 32, PALETTE);
			imageData.setPixels(0, 0, imgData.length, imgData, 0);
			return new Image(parent, imageData);
		} catch (JRException e) {
			throw new ReportException("Could not display report", e);
		}
		
	}
}
